import base64
import pickle
from django.shortcuts import render
from rest_framework import status
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response

from . import serializers
from django_redis import get_redis_connection

from goods.models import SKU


class CartView(GenericAPIView):
    serializer_class = serializers.CartSerializer

    # 重写方法,让未登录用户也能访问该视图
    def perform_authentication(self, request):
        pass

    def post(self, request):
        # 获取数据
        dict_data = request.data
        # 获取序列化器
        serializer = self.get_serializer(data=dict_data)
        serializer.is_valid(raise_exception=True)

        # 获取数据
        sku_id = serializer.data.get("sku_id")
        count = serializer.data.get("count")
        selected = serializer.data.get("selected", True)

        try:
            user = request.user
        except Exception as e:
            user = None  # 如果用户未登录返回空

        # 判断用户状态
        if user and request.user:
            # 获取redis对象
            redis_conn = get_redis_connection("cart")  # 获取redis库

            # 增加购物车商品数量
            redis_conn.hincrby("cart_%s" % user.id, sku_id, count)  # 用户id 商品id 商品数量
            # 判断是否选中/勾选
            if selected:
                redis_conn.sadd("cart_selected_%s" % user.id, sku_id)

            # 返回
            return Response(serializer.data)
        else:
            """# 未登录用户添加购物车"""
            # 获取cookie中的数据
            cookie_cart = request.COOKIES.get("cart")

            # 转换成字典  判断是否有购物车数据
            cookie_dict = {}
            if cookie_cart:
                cookie_dict = pickle.loads(base64.b64decode(cookie_cart.encode()))

            # 累加
            if sku_id in cookie_dict:
                count += cookie_dict[sku_id].get("count", 0)

            # 设置新的购物车数据到字典
            cookie_dict[sku_id] = {
                "count": count,
                "selected": selected
            }
            # 将字典转换成字符串,写入到cookie
            response = Response(status=200)
            cookie_cart = base64.b64encode(pickle.dumps(cookie_dict)).decode()
            response.set_cookie("cart", cookie_cart)
            # 返回响应
            return response

    def get(self, request):
        """
        思路
        #判断是否为登录用户
            #登录用户,从redis中获取数据
            #非登录用户,从cookie中获取数据
        #获取所有商品的信息
        #返回响应
        """
        # 获取用户数据
        try:
            user = request.user
        except Exception as e:
            user = None

        # 判断用户登陆状态
        if user and request.user.is_authenticated:
            # 获取redis中的用户购物车数据
            redis_conn = get_redis_connection("cart")
            redis_cart_dict = redis_conn.hgetall("cart_%s" % user.id)
            redis_cart_selected_list = redis_conn.smembers("cart_selected_%s" % user.id)

            # 数据拼接
            sku_list = []
            for sku_id,count in redis_cart_dict.items():
                sku = SKU.objects.get(id=sku_id)
                sku_dict = {
                    "selected": sku_id in redis_cart_selected_list,
                    "default_image_url": sku.default_image_url,
                    "name": sku.name,
                    "price": sku.price,
                    "count": int(count),
                    "id": sku.id
                }
                sku_list.append(sku_dict)

            # 返回响应
            return Response(sku_list)
        else:
            # 获取cookie中的数据
            cookie_cart = request.COOKIES.get("cart")

            cookie_dict = {}

            if cookie_cart:
                cookie_dict = pickle.loads(base64.b64decode(cookie_cart.encode()))

            # 拼接数据
            sku_list = []
            for sku_id, count_selected in cookie_dict.items():
                sku = SKU.objects.get(id=sku_id)
                sku_dict = {
                    "selected": count_selected["selected"],
                    "default_image_url": sku.default_image_url,
                    "name": sku.name,
                    "price": sku.price,
                    "count": int(count_selected["count"]),
                    "id": sku.id
                }
                sku_list.append(sku_dict)

                # 6,返回响应
            return Response(sku_list)

    """修改购物车信息"""
    def put(self, request):
        # 获取参数
        dict_data = request.data
        # 获取序列化器
        serializer = self.get_serializer(data=dict_data)
        serializer.is_valid(raise_exception=True)
        # 获取数据
        sku_id = serializer.data.get("sku_id")  # 商品编号
        count = serializer.data.get("count")  # 商品数量
        selected = serializer.data.get("selected")  # 商品勾选

        # 判断用户登陆状态
        try:
            user = request.user
        except Exception as e:
            user = None

        if user and request.user.is_authenticated:  # 系统会校验这个用户的认证状态

            # 获取redis中的购物车数据
            redis_conn = get_redis_connection("cart")  # redis中的数据是哈希类型和set类型
            # 修改                       用户编号   商品编号  数量
            redis_conn.hset("cart_%s" % user.id, sku_id, count)
            if selected:
                redis_conn.sadd("cart_selected_%s" % user.id, sku_id)  # 如果勾选为True就添加进set合集
            else:
                redis_conn.srem("cart_selected_%s" % user.id, sku_id)
            # 返回响应
            return Response(serializer.data)
        # 用户未登录时执行
        else:
            # 获取cookie数据
            cookie_cart = request.COOKIES.get("cert")
            # 转换字典
            cookie_dict = {}
            if cookie_cart:
                cookie_dict = pickle.loads(base64.b64decode(cookie_cart.encode()))
                # 使用pickle转成字典,base64.b64decode得到转八位,base64.b64encode转六位
            # 修改 商品编号的数量和勾选状态
            cookie_dict[sku_id] = {
                "count": count,
                "selected": selected
            }
            # 转换成字符串返回
            response = Response(serializer.data)
            cookie_cart = base64.b64encode(pickle.dumps(cookie_dict)).decode()
            # 使用b64encode转换成六位数的二进制最后使用decode转成字符串
            response.set_cookie("cart", cookie_cart)
            return response

    """购物车商品删除"""
    def delete(self, request):
        # 获取参数
        dict_data = request.data
        # 创建序列化器
        serializer = serializers.CartDeleteSerializer(data=dict_data)
        serializer.is_valid(raise_exception=True)
        # 获取数据
        sku_id = serializer.data.get("sku_id")

        # 判断用户状态
        try:
            user = request.user
        except Exception as e:
            user = None
        if user and request.user.is_authenticated:
            # 删除redis中的数据
            redis_conn = get_redis_connection("cart")   # 获得redis库对象
            redis_conn.hdel("cart_%s" % user.id, sku_id)    # 哈希删除使用hdel
            redis_conn.srem("cart_selected_%s" % user.id, sku_id)  # set删除使用srem
            # 返回响应
            return Response(status=status.HTTP_204_NO_CONTENT)
        else:
            # 获取cookie中的数据
            cookie_cary = request.COOKIES.get("cart")

            # 字典转换
            cookie_dict = {}
            if cookie_cary:
                cookie_dict = pickle.loads(base64.b64decode(cookie_cary.encode()))

            # 删除
            if sku_id in cookie_dict:
                del cookie_dict[sku_id]
            # 返回响应
            response = Response(serializer.data)
            cookie_cary = base64.b64encode(pickle.dumps(cookie_dict)).decode()
            response.set_cookie("cart", cookie_cary)
            return response
